/*
 * Copyright 2005 PayPal, Inc. All Rights Reserved.
 */
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using com.paypal.sdk.exceptions;
using com.paypal.sdk.profiles;
using com.paypal.sdk.util;

namespace com.paypal.sdk.core
{
	/// <summary>
	/// Main class used to invoke API calls
	/// </summary>
	public abstract class APICallerBase
	{
		private IAPIProfile profile = null;

		/// <summary>
		/// Default constructor
		/// </summary>
		protected APICallerBase()
		{
			SetTrustManager();
		}

		/// <summary>
		/// API profile
		/// </summary>
		public IAPIProfile Profile
		{
			get { return this.profile; }
			set
			{
				validateProfile(value);
				this.SetupConnection(value);
				this.profile = value;
			}
		}

		/// <summary>
		/// Retrieve the X509 certificate from keystores.
		/// </summary>
		/// <param name="name">name of the certificate</param>
		/// <returns>x509 certificate</returns>
		/// <exception cref="PayPalException">If the certificate cannot be found</exception>
		public static X509Certificate GetCertificate(string name)
		{
			IntPtr hCertCntxt = IntPtr.Zero;

			uint openflags = Crypto32API.CERT_SYSTEM_STORE_LOCAL_MACHINE | Crypto32API.CERT_STORE_READONLY_FLAG;
			IntPtr hSysStore =
				Crypto32API.CertOpenStore((IntPtr) Crypto32API.CERT_STORE_PROV_LM_SYSTEM_STORE, 0, IntPtr.Zero, openflags,
				                          Crypto32API.MY_STORE);
			if (hSysStore != IntPtr.Zero)
			{
				while (IntPtr.Zero != (hCertCntxt = Crypto32API.CertEnumCertificatesInStore(hSysStore, hCertCntxt)))
				{
					X509Certificate x509 = new X509Certificate(hCertCntxt);
					if (x509.GetName().ToLower().IndexOf(name.Trim().ToLower()) >= 0)
					{
						Crypto32API.CertCloseStore(hSysStore, 0);
						return x509;
					}
				}
			}
			Crypto32API.CertCloseStore(hSysStore, 0);

			openflags = Crypto32API.CERT_SYSTEM_STORE_MYSUSER_MACHINE | Crypto32API.CERT_STORE_READONLY_FLAG;
			hSysStore =
				Crypto32API.CertOpenStore((IntPtr) Crypto32API.CERT_STORE_PROV_LM_SYSTEM_STORE, 0, IntPtr.Zero, openflags,
				                          Crypto32API.MY_STORE);
			if (hSysStore != IntPtr.Zero)
			{
				while (IntPtr.Zero != (hCertCntxt = Crypto32API.CertEnumCertificatesInStore(hSysStore, hCertCntxt)))
				{
					X509Certificate x509 = new X509Certificate(hCertCntxt);
					if (x509.GetName().ToLower().IndexOf(name.Trim().ToLower()) >= 0)
					{
						Crypto32API.CertCloseStore(hSysStore, 0);
						return x509;
					}
				}
			}
			Crypto32API.CertCloseStore(hSysStore, 0);
			throw new FatalException(MessageResources.GetMessage("CERTIFICATE_NOT_FOUND") + name);
		} // GetCertificate

		/// <summary>
		/// To Accept all un-trusted certificate
		/// </summary>
		private void SetTrustManager()
		{
			//This code is added to accept all un-trusted certificate i.e self-signed certificate
			if (Config.Instance.TrustAll)
			{
			//	ServicePointManager.CertificatePolicy = TrustAllCertificatePolicy.Instance;
				ServicePointManager.CertificatePolicy = new MyPolicy();
				
			}
		} // SetTrustManager

		/// <summary>
		/// abstract SetupConnection
		/// </summary>
		/// <param name="cprofile"></param>
		protected abstract void SetupConnection(IAPIProfile cprofile);

		/// <summary>
		/// Validates the profile
		/// </summary>
		/// <param name="_profile"></param>
		protected virtual void validateProfile(IAPIProfile _profile)
		{
			if (_profile == null)
			{
				throw new WarningException(MessageResources.GetMessage("PROFILE_INVALID"));
			}
		}
	} // APICallerBase	
} // core namespace